﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using ShredTheLog.Api.DataContracts;
using System.Diagnostics.Contracts;

namespace ShredTheLog.Api
{
    [ContractClass(typeof(TranslatorBase_Contract))]
    public interface ITranslatorBase
    {
        IObservable<TranslateResponse> Translate(TranslateRequest translateRequest, bool ignoreErrors);
        IObservable<DetectResponse> Detect(string text);
        IEnumerable<Language> SupportedLanguages { get; }
    }

    [ContractClassFor(typeof(ITranslatorBase))]
    internal abstract class TranslatorBase_Contract : ITranslatorBase
    {
        IObservable<TranslateResponse> ITranslatorBase.Translate(TranslateRequest translateRequest, bool ignoreErrors)
        {
            Contract.Requires(translateRequest != null);
            Contract.Ensures(Contract.Result<IObservable<TranslateResponse>>() != null);
            throw new NotImplementedException();
        }

        IObservable<DetectResponse> ITranslatorBase.Detect(string text)
        {
            Contract.Ensures(Contract.Result<IObservable<DetectResponse>>() != null);
            throw new NotImplementedException();
        }

        IEnumerable<Language> ITranslatorBase.SupportedLanguages
        {
            get 
            {
                Contract.Ensures(Contract.Result<IEnumerable<Language>>() != null);
                throw new NotImplementedException(); 
            }
        }
    }

    [ContractClass(typeof(Translator_Contract))]
    public interface ITranslator : ITranslatorBase
    {
        string ID { get; }
        string Name { get; }
    }

    [ContractClassFor(typeof(ITranslator))]
    internal abstract class Translator_Contract : ITranslator
    {
        string ITranslator.ID
        {
            get 
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException(); 
            }
        }

        string ITranslator.Name
        {
            get 
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException(); 
            }
        }

        IObservable<TranslateResponse> ITranslatorBase.Translate(TranslateRequest translateRequest, bool ignoreErrors)
        {
            throw new NotImplementedException();
        }

        IObservable<DetectResponse> ITranslatorBase.Detect(string text)
        {
            throw new NotImplementedException();
        }

        IEnumerable<Language> ITranslatorBase.SupportedLanguages
        {
            get 
            {
                throw new NotImplementedException(); 
            }
        }
    }

    public sealed class TranslateRequest
    {
        public string Text { get; private set; }
        public Language? SourceLanguage { get; private set; }
        public Language TargetLanguage { get; private set; }
        public object Context { get; private set; }

        public TranslateRequest(string text, Language? sourceLanguage, Language targetLanguage, object context)
        {
            Text = text;
            SourceLanguage = sourceLanguage;
            TargetLanguage = targetLanguage;
            Context = context;
        }

        public override int GetHashCode()
        {
            return Text != null ? Text.GetHashCode() : 0 ^ SourceLanguage.GetHashCode() ^ TargetLanguage.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            var o = obj as TranslateRequest;
            if (o != null)
                return Text == o.Text && SourceLanguage == o.SourceLanguage && TargetLanguage == o.TargetLanguage;
            else
                return base.Equals(obj);
        }
    }

    public sealed class TranslateResponse
    {
        public string Text { get; private set; }
        public Language DetectedSourceLanguage { get; private set; }
        public object Context { get; private set; }

        public TranslateResponse(string text, Language detectedSourceLanguage, object context)
        {
            Text = text;
            DetectedSourceLanguage = detectedSourceLanguage;
            Context = context;
        }

        public override string ToString()
        {
            return String.Format(CultureInfo.CurrentCulture, "Text = \"{0}\"; DetectedSourceLanguage = {1}", 
                Text ?? String.Empty, 
                DetectedSourceLanguage.ToString());
        }
    }

    public class DetectResponse
    {
        public Language DetectedLanguage { get; private set; }

        public DetectResponse(Language detectedLanguage)
        {
            DetectedLanguage = detectedLanguage;
        }

        public override string ToString()
        {
            return String.Format(CultureInfo.CurrentCulture, "DetectedLanguage = {0}", DetectedLanguage.ToString());
        }
    }
}
